home *** CD-ROM | disk | FTP | other *** search
/ Sun Solutions 1997 April to September / Sun Solutions CD - APR '97 - SEP '97 (704-3778-12 Rev. H)(Sun Microsystems, Inc.)(1997).iso / products / Hyperion / src / drv_sony.c < prev    next >
C/C++ Source or Header  |  1997-02-26  |  3KB  |  145 lines

  1. /*
  2.  * @(#)drv_sony.c    1.1    12/21/93
  3.  *
  4.  * Vendor-specific drive control routines for Sony CDU-8012 series.
  5.  */
  6. static char *ident = "@(#)drv_sony.c    1.1 12/21/93";
  7.  
  8. #include <stdio.h>
  9. #include <errno.h>
  10. #include "struct.h"
  11.  
  12. #define PAGE_AUDIO        0x0e
  13.  
  14. static int    sony_init(), sony_set_volume(), sony_get_volume();
  15.  
  16. extern int    min_volume, max_volume;
  17.  
  18. struct wm_drive sony_proto = {
  19.     -1,            /* fd */
  20.     "Sony",            /* vendor */
  21.     "CDU-8012",        /* model */
  22.     NULL,            /* aux */
  23.     NULL,            /* daux */
  24.  
  25.     sony_init,        /* functions... */
  26.     gen_get_trackcount,
  27.     gen_get_cdlen,
  28.     gen_get_trackinfo,
  29.     gen_get_drive_status,
  30.     sony_get_volume,
  31.     sony_set_volume,
  32.     gen_pause,
  33.     gen_resume,
  34.     gen_stop,
  35.     gen_play,
  36.     gen_eject
  37. };
  38.  
  39. /*
  40.  * Initialize the driver.
  41.  */
  42. static int
  43. sony_init(d)
  44.     struct wm_drive    *d;
  45. {
  46.     min_volume = 128;
  47.     max_volume = 255;
  48. }
  49.  
  50. /*
  51.  * On the Sony CDU-8012 drive, the amount of sound coming out the jack
  52.  * increases much faster toward the top end of the volume scale than it
  53.  * does at the bottom.  To make up for this, we make the volume scale look
  54.  * sort of logarithmic (actually an upside-down inverse square curve) so
  55.  * that the volume value passed to the drive changes less and less as you
  56.  * approach the maximum slider setting.  Additionally, only the top half
  57.  * of the volume scale is valid; the bottom half is all silent.  The actual
  58.  * formula looks like
  59.  *
  60.  *     max^2 - (max - vol)^2   max
  61.  * v = --------------------- + ---
  62.  *            max * 2           2
  63.  *
  64.  * Where "max" is the maximum value of the volume scale, usually 100.
  65.  */
  66. static int
  67. scale_volume(vol, max)
  68.     int    vol, max;
  69. {
  70.     vol = (max*max - (max - vol) * (max - vol)) / max;
  71.     return ((vol + max) / 2);
  72. }
  73.  
  74. /*
  75.  * Given a value between min_volume and max_volume, return the standard-scale
  76.  * volume value needed to achieve that hardware value.
  77.  *
  78.  * Rather than perform floating-point calculations to reverse the above
  79.  * formula, we simply do a binary search of scale_volume()'s return values.
  80.  */
  81. static int
  82. unscale_volume(cd_vol, max)
  83.     int    cd_vol, max;
  84. {
  85.     int    vol = 0, top = max, bot = 0, scaled;
  86.  
  87.     cd_vol = (cd_vol * 100 + (max_volume - 1)) / max_volume;
  88.  
  89.     while (bot <= top)
  90.     {
  91.         vol = (top + bot) / 2;
  92.         scaled = scale_volume(vol, max);
  93.         if (cd_vol <= scaled)
  94.             top = vol - 1;
  95.         else
  96.             bot = vol + 1;
  97.     }
  98.     
  99.     /* Might have looked down too far for repeated scaled values */
  100.     if (cd_vol < scaled)
  101.         vol++;
  102.  
  103.     if (vol < 0)
  104.         vol = 0;
  105.     else if (vol > max)
  106.         vol = max;
  107.  
  108.     return (vol);
  109. }
  110.  
  111. /*
  112.  * Get the volume.  Sun's CD-ROM driver doesn't support this operation, even
  113.  * though their drive does.  Dumb.
  114.  */
  115. static int
  116. sony_get_volume(d, left, right)
  117.     struct wm_drive    *d;
  118.     int        *left, *right;
  119. {
  120.     unsigned char    mode[16];
  121.  
  122.     /* Get the current audio parameters first. */
  123.     if (wm_scsi_mode_sense(d, PAGE_AUDIO, mode))
  124.         return (-1);
  125.  
  126.     *left = unscale_volume(mode[9], 100);
  127.     *right = unscale_volume(mode[11], 100);
  128.  
  129.     return (0);
  130. }
  131.  
  132. /*
  133.  * Set the volume using the wacky scale outlined above.  The Sony drive
  134.  * responds to the standard set-volume command.
  135.  */
  136. static int
  137. sony_set_volume(d, left, right)
  138.     struct wm_drive    *d;
  139.     int        left, right;
  140. {
  141.     left = scale_volume(left, 100);
  142.     right = scale_volume(right, 100);
  143.     return (gen_set_volume(d, left, right));
  144. }
  145.